package com.job.core.executor;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import com.job.core.biz.ExecutorBiz;
import com.job.core.biz.impl.ExecutorBizImpl;
import com.job.core.handler.BaseJobHandler;
import com.job.core.handler.annotation.JobHandler;
import com.job.core.register.RegistHandlerHelper;
import com.job.core.rpc.NetComServerFactory;
import com.job.core.thread.ExecuRegistThread;
import com.job.core.thread.JobThread;
import com.job.core.thread.TriggerCallBackThread;
/**
 * 
 * @Title: JobExecutor.java
 * @Package: com.job.core.executor
 * @Description: job执行
 * @author: sunwei
 * @date: 2017年5月15日 上午11:30:48
 * @version: V1.0
 */
public class JobExecutor implements ApplicationContextAware,ApplicationListener {
    private static final Logger logger = LoggerFactory.getLogger(JobExecutor.class);

    private String ip;
    private int port = 9999;
    private String appName;
    private RegistHandlerHelper registHelper;
    public static String logPath;
    public void setIp(String ip) {
        this.ip = ip;
    }
    public void setPort(int port) {
        this.port = port;
    }
    public void setAppName(String appName) {
        this.appName = appName;
    }
    public void setRegistHelper(RegistHandlerHelper registHelper) {
        this.registHelper = registHelper;
    }
    public void setLogPath(String logPath) {
        this.logPath = logPath;
    }
    /*******************job server**********************************/
    private NetComServerFactory serverFactory = new NetComServerFactory();
    /**
     * 
     * @Title: start
     * @Description:job启动
     * @author:sunwei
     * @throws Exception  if have a start error
     * @createTime:2017年5月15日上午11:52:41
     */
    public void start() throws Exception{
	// executor start
        NetComServerFactory.putService(ExecutorBiz.class, new ExecutorBizImpl());
        serverFactory.start(port, ip, appName, registHelper);
        // trigger callback thread start
        TriggerCallBackThread.getInstance().start();
    }
    /**
     * 
     * @Title: destroy
     * @Description:销毁wen容器
     * @author:sunwei
     * @createTime:2017年5月15日上午11:55:04
     */
    public void destroy(){
        // executor stop
        serverFactory.destroy();
        // job thread repository destory
        if (jobThreadRepository.size() > 0) {
            for (Map.Entry<Long, JobThread> item: jobThreadRepository.entrySet()) {
                JobThread jobThread = item.getValue();
                jobThread.toStop("Web容器销毁终止");
                jobThread.interrupt();

            }
            jobThreadRepository.clear();
        }
        // trigger callback thread stop
        TriggerCallBackThread.getInstance().toStop();
        // executor registry thread stop
        ExecuRegistThread.getExecuRegistThread().toStop();
    }
    // ---------------------------------- init job handler ------------------------------------
    public static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
	JobExecutor.applicationContext=applicationContext;//初始化上下文
	// init job handler action 得到所有的注解集合
        Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);
	if(null!=serviceBeanMap && serviceBeanMap.size()>0){
	    for(Map.Entry<String, Object> serviceBean:serviceBeanMap.entrySet()){
		if(serviceBean.getValue() instanceof BaseJobHandler){//如果是执行器类型
		    String name=serviceBean.getValue().getClass().getAnnotation(JobHandler.class).value();//类信息
		    BaseJobHandler jobHandler=(BaseJobHandler)serviceBean.getValue();//具体handler实例
		    //
		}
	    }
	}
    }
    /******************将job执行器放入****************************/
    //执行期注册中
    private static ConcurrentHashMap<String, BaseJobHandler> jobHandlerRepository = new ConcurrentHashMap<String, BaseJobHandler>();
    /**
     * 
     * @Title: registeryhandler
     * @Description:将具体job执行器放入dui l
     * @author:sunwei
     * @createTime:2017年5月15日下午1:57:08
     * @param className 执行器名称
     * @param jobHandler 具体执行器实例
     * @return 执行器实例
     */
    public static BaseJobHandler registeryhandler(String className,BaseJobHandler jobHandler){
	logger.info("执行器【"+className+"】 注册成功！！！！");
	return jobHandlerRepository.put(className, jobHandler);
    }
    /**
     * 
     * @Title: loadJobHandler
     * @Description:根据handler名称获取类实例
     * @author:sunwei
     * @createTime:2017年5月15日下午2:22:06
     * @param className handler注解名称
     * @return handler处理实例
     */
    public static BaseJobHandler loadJobHandler(String className){
	 logger.info("handler annotation name is 【"+className+"】获取实例");
	 return jobHandlerRepository.get(className);
    }
    
    /*******************jobThread存储和获取********************************/
    //job线程存储
    private static ConcurrentHashMap<Long, JobThread> jobThreadRepository = new ConcurrentHashMap<Long, JobThread>();
    /**
     * 
     * @Title: registryJobThread
     * @Description:将具体job放入执行器中
     * @author:sunwei
     * @createTime:2017年5月15日下午2:26:52
     * @param jobId 任务编号
     * @param jobHandler 执行器
     * @return job执行线程
     */
    public static JobThread registryJobThread(Long jobId,BaseJobHandler jobHandler){
	JobThread jobThread=new JobThread(jobHandler);//将执行器放入线程
	jobThread.start();//启动线程
        logger.info(">>>>>>>>>>> job regist JobThread success, jobId:{}, handler:{}", new Object[]{jobId, jobHandler});
	jobThreadRepository.put(jobId, jobThread);//不能用传统map 因为传统map 有可能会用old value
	return jobThread;
    }
    /**
     * 
     * @Title: loadJobThread
     * @Description:根据jobId 获取job任务执行线程
     * @author:sunwei
     * @createTime:2017年5月15日下午2:31:23
     * @param jobId job任务编号
     * @return job执行器线程
     */
    public static JobThread loadJobThread(Long jobId){
	return jobThreadRepository.get(jobId);
    }
    /**
     * 
     * @Title: removeJobThread
     * @Description:删除job任务线程
     * @author:sunwei
     * @createTime:2017年5月15日下午2:33:12
     * @param jobId job任务编号
     */
    public static void removeJobThread(Long jobId){
	jobThreadRepository.remove(jobId);
	logger.info("remove jobId:{} is success!",new Object []{jobId});
    }
    
    
    @Override
    public void onApplicationEvent(ApplicationEvent arg0) {
	// TODO Auto-generated method stub
	
    }
}
